package setting

import (
	"context"
	"strconv"
	"strings"

	"mall/common/globalkey"
	"mall/common/utils/pointy"
	"mall/service/backend/api/internal/logic/product/util"
	"mall/service/backend/api/internal/logic/utils/parse"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/common/i18n"
	"mall/service/backend/common/utils/miniapp"
	"mall/service/product/rpc/productclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetSettingProductListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetSettingProductListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSettingProductListLogic {
	return &GetSettingProductListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetSettingProductListLogic) GetSettingProductList(req *types.SectionProductListReq) (resp *types.SectionProductListResp, err error) {
	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	orderBys := util.ParseSorterNew(req.Sorter)
	filterBys := util.ParseFilterNew(req.Filter, req.Type)

	var ids *string
	var search *string
	if req.Search != nil && len(strings.TrimSpace(*req.Search)) > 0 { // 前端可以搜标题或者ID
		reqSearch := strings.TrimSpace(*req.Search)
		if _, err := strconv.ParseInt(reqSearch, 10, 64); err == nil {
			ids = pointy.GetPointer(reqSearch)
		} else {
			search = pointy.GetPointer(strings.TrimSuffix(reqSearch, ","))
		}
	}
	if req.Id != nil && *req.Id > 0 {
		ids = pointy.GetPointer(strconv.FormatInt(int64(*req.Id), 10))
	}
	if req.ProductIds != nil && len(strings.TrimSpace(*req.ProductIds)) > 0 {
		ids = pointy.GetPointer(strings.TrimSpace(*req.ProductIds))
	}

	data, err := l.svcCtx.ProductRpc.BackendGetProductList(l.ctx, &productclient.ProductListReq{
		Page:      page,
		PageSize:  pageSize,
		Ids:       ids,
		Title:     req.Title,
		Slug:      req.Slug,
		Status:    req.Status,
		Search:    search,
		StartTime: req.StartTime,
		EndTime:   req.EndTime,
		WithMeta:  req.WithMeta,
		WithMedia: req.WithMedia,
		WithSku:   req.WithMeta,
		OrderBy:   orderBys,
		FilterBy:  filterBys,
	})
	if err != nil {
		return nil, err
	}

	var withLink bool
	if req.WithLink != nil && *req.WithLink > 0 {
		withLink = true
	}

	resp = &types.SectionProductListResp{
		BaseDataInfo: types.BaseDataInfo{
			Success: true,
			Msg:     l.svcCtx.Trans.Trans(l.ctx, i18n.Success),
		},
		Data: types.SectionProductListInfo{
			BaseListInfo: types.BaseListInfo{
				Current:  page,
				PageSize: pageSize,
				Total:    data.GetTotal(),
			},
		},
	}
	for _, v := range data.List {
		var media []*types.MediaInfo
		if len(v.Media) > 0 {
			for _, m := range v.Media {
				var url *string
				if m.Url != nil {
					url = m.Url
				} else if m.Uri != nil {
					url = m.Uri
				}
				media = append(media, &types.MediaInfo{
					Id:        m.Id,
					Thumbnail: m.Thumbnail,
					Url:       url,
				})
			}
		}
		var brandId *uint64
		var brandName *string
		var brandSlug *string
		if len(v.Relations) > 0 {
			for _, entry := range v.Relations {
				if entry.Key != nil && *entry.Key == globalkey.ProductRelationNameBrand {
					brandId = entry.Id
					brandName = entry.Name
					brandSlug = entry.Slug
					break
				}
			}
		}

		var link *string
		if withLink {
			link = pointy.GetPointer(miniapp.GetProductLinkUrl(v.Id))
		}
		var label *string
		if len(v.Skus) > 0 {
			var labels []string
			for _, sv := range v.Skus {
				if len(sv.Specs) > 0 {
					for _, spec := range sv.Specs {
						var opts []string
						if len(spec.Options) > 0 {
							for _, opt := range spec.Options {
								if opt.Label != nil && len(*opt.Label) > 0 {
									opts = append(opts, *opt.Label)
								}
							}
						}
						labels = append(labels, strings.Join(opts, ","))
					}
				}
			}
			label = pointy.GetPointer(strings.Join(labels, ";"))
		}
		var price *string
		if len(v.Meta) > 0 {
			for _, mv := range v.Meta {
				if mv.Key == nil || mv.Value == nil {
					continue
				}

				val := *mv.Value
				switch *mv.Key {
				case "retailPriceMin":
					price = pointy.GetPointer(val)
				}
			}
		}

		resp.Data.List = append(resp.Data.List, &types.SectionProductInfo{
			Id:        v.Id,
			Title:     v.Title,
			Slug:      v.Slug,
			BrandId:   brandId,
			BrandName: brandName,
			BrandSlug: brandSlug,
			Sort:      v.Sort,
			Status:    v.Status,
			Link:      link,
			Label:     label,
			Price:     price,
			Media:     media,
		})
	}

	return resp, nil
}
